1 // Written in the D programming language
2 
3 // NOTE: When working on this module, be sure to run tests with -debug=std_socket
4 // E.g.: dmd -version=StdUnittest -debug=std_socket -unittest -main -run socket
5 // This will enable some tests which are too slow or flaky to run as part of CI.
6 
7 /*
8         Copyright (C) 2004-2011 Christopher E. Miller
9 
10         socket.d 1.4
11         Jan 2011
12 
13         Thanks to Benjamin Herr for his assistance.
14  */
15 
16 /**
17  * Socket primitives.
18  * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
19  * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
20  * Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
21  *      $(HTTP thecybershadow.net, Vladimir Panteleev)
22  * Source:  $(PHOBOSSRC std/socket.d)
23  */
24 module std.socket;
25 
26 
27 import core.stdc.stdint,
28     core.stdc.stdlib,
29     core.stdc.string,
30     std.string;
31 
32 import hip.util.conv:to;
33 import hip.util.string:isNumber;
34 
35 import core.stdc.config;
36 import std.exception;
37 
38 import std.internal.cstring;
39 
40 version (iOS)
41     version = iOSDerived;
42 else version (TVOS)
43     version = iOSDerived;
44 else version (WatchOS)
45     version = iOSDerived;
46 
47 @safe:
48 
49 version(Posix) version = LinuxLike;
50 version(PSVita) version = LinuxLike;
51 
52 version(PSVita):
53 
54 version (Windows)
55 {
56     pragma (lib, "ws2_32.lib");
57     pragma (lib, "wsock32.lib");
58 
59     import core.sys.windows.winbase, std.windows.syserror;
60     public import core.sys.windows.winsock2;
61     private alias _ctimeval = core.sys.windows.winsock2.timeval;
62     private alias _clinger = core.sys.windows.winsock2.linger;
63 
64     enum socket_t : SOCKET { INVALID_SOCKET }
65     private const int _SOCKET_ERROR = SOCKET_ERROR;
66 
67 
68     private int _lasterr() nothrow @nogc
69     {
70         return WSAGetLastError();
71     }
72 }
73 else version (LinuxLike)
74 {
75     version (linux)
76     {
77         enum : int
78         {
79             TCP_KEEPIDLE  = 4,
80             TCP_KEEPINTVL = 5
81         }
82         public import core.sys.posix.netinet.in_;
83         import core.sys.posix.arpa.inet;
84         import core.sys.posix.fcntl;
85         import core.sys.posix.netdb;
86         import core.sys.posix.netinet.tcp;
87         import core.sys.posix.sys.select;
88         import core.sys.posix.sys.socket;
89         import core.sys.posix.sys.time;
90         import core.sys.posix.sys.un : sockaddr_un;
91         import core.sys.posix.unistd;
92         private alias _ctimeval = core.sys.posix.sys.time.timeval;
93         private alias _clinger = core.sys.posix.sys.socket.linger;
94         import core.stdc.errno;
95 
96     }
97     else version(PSVita)
98     {
99         import std.vita.tcp;
100         import std.vita.inet;
101         import std.vita.endian;
102         import std.vita.errno;
103         import std.vita.socket;
104         import std.vita.compat;
105         import std.vita.netinet_in;
106         import std.vita.netdb;
107 
108         enum O_NONBLOCK = 0x4000;
109         enum F_GETFL = 3;
110         enum F_SETFL = 4;
111         @nogc @trusted nothrow extern(C) extern int fcntl (int, int, ...);
112         @nogc @trusted nothrow extern(C) int     close(int);
113 
114         extern(C) int     gethostname(char*, size_t);
115         protoent* getprotobyname(T)(T str){return null; }
116 
117         extern(C) @nogc @trusted nothrow int select(int, fd_set*, fd_set*, fd_set*, timeval*);
118     }
119 
120 
121 
122     enum socket_t : int32_t { _init = -1 }
123     private const int _SOCKET_ERROR = -1;
124 
125     private enum : int
126     {
127         SD_RECEIVE = SHUT_RD,
128         SD_SEND    = SHUT_WR,
129         SD_BOTH    = SHUT_RDWR
130     }
131 
132     private int _lasterr() nothrow @nogc
133     {
134         return errno;
135     }
136 }
137 else
138 {
139     static assert(0, "No socket support for this platform yet.");
140 }
141 
142 
143 /// Base exception thrown by `std.socket`.
144 class SocketException: Exception
145 {
146     mixin basicExceptionCtors;
147 }
148 
149 version (CRuntime_Glibc) version = GNU_STRERROR;
150 version (CRuntime_UClibc) version = GNU_STRERROR;
151 
152 /*
153  * Needs to be public so that SocketOSException can be thrown outside of
154  * std.socket (since it uses it as a default argument), but it probably doesn't
155  * need to actually show up in the docs, since there's not really any public
156  * need for it outside of being a default argument.
157  */
158 string formatSocketError(int err) @trusted
159 {
160     version (LinuxLike)
161     {
162         char[80] buf;
163         const(char)* cs;
164         version (GNU_STRERROR)
165         {
166             cs = strerror_r(err, buf.ptr, buf.length);
167         }
168         else
169         {
170             auto errs = strerror_r(err, buf.ptr, buf.length);
171             if (errs == 0)
172                 cs = buf.ptr;
173             else
174                 return "Socket error " ~ to!string(err);
175         }
176 
177         auto len = strlen(cs);
178 
179         if (cs[len - 1] == '\n')
180             len--;
181         if (cs[len - 1] == '\r')
182             len--;
183         return cs[0 .. len].idup;
184     }
185     else
186     version (Windows)
187     {
188         return generateSysErrorMsg(err);
189     }
190     else
191         return "Socket error " ~ to!string(err);
192 }
193 
194 /// Returns the error message of the most recently encountered network error.
195 @property string lastSocketError()
196 {
197     return formatSocketError(_lasterr());
198 }
199 
200 /// Socket exception representing network errors reported by the operating system.
201 class SocketOSException: SocketException
202 {
203     int errorCode;     /// Platform-specific error code.
204 
205     ///
206     this(string msg,
207          string file = __FILE__,
208          size_t line = __LINE__,
209          Throwable next = null,
210          int err = _lasterr(),
211          string function(int) @trusted errorFormatter = &formatSocketError)
212     {
213         errorCode = err;
214 
215         if (msg.length)
216             super(msg ~ ": " ~ errorFormatter(err), file, line, next);
217         else
218             super(errorFormatter(err), file, line, next);
219     }
220 
221     ///
222     this(string msg,
223          Throwable next,
224          string file = __FILE__,
225          size_t line = __LINE__,
226          int err = _lasterr(),
227          string function(int) @trusted errorFormatter = &formatSocketError)
228     {
229         this(msg, file, line, next, err, errorFormatter);
230     }
231 
232     ///
233     this(string msg,
234          int err,
235          string function(int) @trusted errorFormatter = &formatSocketError,
236          string file = __FILE__,
237          size_t line = __LINE__,
238          Throwable next = null)
239     {
240         this(msg, file, line, next, err, errorFormatter);
241     }
242 }
243 
244 /// Socket exception representing invalid parameters specified by user code.
245 class SocketParameterException: SocketException
246 {
247     mixin basicExceptionCtors;
248 }
249 
250 /**
251  * Socket exception representing attempts to use network capabilities not
252  * available on the current system.
253  */
254 class SocketFeatureException: SocketException
255 {
256     mixin basicExceptionCtors;
257 }
258 
259 
260 /**
261  * Returns:
262  * `true` if the last socket operation failed because the socket
263  * was in non-blocking mode and the operation would have blocked,
264  * or if the socket is in blocking mode and set a `SNDTIMEO` or `RCVTIMEO`,
265  * and the operation timed out.
266  */
267 bool wouldHaveBlocked() nothrow @nogc
268 {
269     version (Windows)
270         return _lasterr() == WSAEWOULDBLOCK || _lasterr() == WSAETIMEDOUT;
271     else version (LinuxLike)
272         return _lasterr() == EAGAIN;
273     else
274         static assert(0, "No socket support for this platform yet.");
275 }
276 
277 
278 version(Windows)
279 {
280     private immutable
281     {
282         typeof(&getnameinfo) getnameinfoPointer;
283         typeof(&getaddrinfo) getaddrinfoPointer;
284         typeof(&freeaddrinfo) freeaddrinfoPointer;
285     }
286 }
287 else
288 {
289     private immutable
290     {
291         typeof(&getaddrinfo) getaddrinfoPointer = &getaddrinfo;
292         typeof(&freeaddrinfo) freeaddrinfoPointer = &freeaddrinfo;
293         version(linux)
294             typeof(&getnameinfo) getnameinfoPointer = &getnameinfo;
295     }
296 }
297 
298 shared static this() @system
299 {
300     version (Windows)
301     {
302         WSADATA wd;
303 
304         // Winsock will still load if an older version is present.
305         // The version is just a request.
306         int val;
307         val = WSAStartup(0x2020, &wd);
308         if (val)         // Request Winsock 2.2 for IPv6.
309             throw new SocketOSException("Unable to initialize socket library", val);
310 
311         // These functions may not be present on older Windows versions.
312         // See the comment in InternetAddress.toHostNameString() for details.
313         auto ws2Lib = GetModuleHandleA("ws2_32.dll");
314         if (ws2Lib)
315         {
316             getnameinfoPointer = cast(typeof(getnameinfoPointer))
317                                  GetProcAddress(ws2Lib, "getnameinfo");
318             getaddrinfoPointer = cast(typeof(getaddrinfoPointer))
319                                  GetProcAddress(ws2Lib, "getaddrinfo");
320             freeaddrinfoPointer = cast(typeof(freeaddrinfoPointer))
321                                  GetProcAddress(ws2Lib, "freeaddrinfo");
322         }
323     }
324 }
325 
326 
327 
328 version(Windows)
329 {
330     shared static ~this() @system nothrow @nogc
331     {
332         WSACleanup();
333     }
334 }
335 
336 
337 /**
338  * The communication domain used to resolve an address.
339  */
340 enum AddressFamily: ushort
341 {
342     UNSPEC =     AF_UNSPEC,     /// Unspecified address family
343     UNIX =       AF_UNIX,       /// Local communication (Unix socket)
344     INET =       AF_INET,       /// Internet Protocol version 4
345     IPX =        AF_IPX,        /// Novell IPX
346     APPLETALK =  AF_APPLETALK,  /// AppleTalk
347     INET6 =      AF_INET6,      /// Internet Protocol version 6
348 }
349 
350 
351 /**
352  * Communication semantics
353  */
354 enum SocketType: int
355 {
356     STREAM =     SOCK_STREAM,           /// Sequenced, reliable, two-way communication-based byte streams
357     DGRAM =      SOCK_DGRAM,            /// Connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
358     RAW =        SOCK_RAW,              /// Raw protocol access
359     RDM =        SOCK_RDM,              /// Reliably-delivered message datagrams
360     SEQPACKET =  SOCK_SEQPACKET,        /// Sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
361 }
362 
363 version(PSVita)
364 {
365     /**
366     * Protocol
367     */
368     enum ProtocolType: int
369     {
370         IP =    IPPROTO_IP,         /// Internet Protocol version 4
371         ICMP =  IPPROTO_ICMP,       /// Internet Control Message Protocol
372         IGMP =  IPPROTO_IGMP,       /// Internet Group Management Protocol
373         TCP =   IPPROTO_TCP,        /// Transmission Control Protocol
374         UDP =   IPPROTO_UDP,        /// User Datagram Protocol
375         IPV6 =  IPPROTO_IPV6,       /// Internet Protocol version 6
376 
377         GGP = int.max,
378         PUP = int.max,
379         IDP = int.max,
380         RAW = int.max,        /// Raw IP packets
381     }
382 }
383 else
384 {
385     /**
386     * Protocol
387     */
388     enum ProtocolType: int
389     {
390         IP =    IPPROTO_IP,         /// Internet Protocol version 4
391         ICMP =  IPPROTO_ICMP,       /// Internet Control Message Protocol
392         IGMP =  IPPROTO_IGMP,       /// Internet Group Management Protocol
393         GGP =   IPPROTO_GGP,        /// Gateway to Gateway Protocol
394         TCP =   IPPROTO_TCP,        /// Transmission Control Protocol
395         PUP =   IPPROTO_PUP,        /// PARC Universal Packet Protocol
396         UDP =   IPPROTO_UDP,        /// User Datagram Protocol
397         IDP =   IPPROTO_IDP,        /// Xerox NS protocol
398         RAW =   IPPROTO_RAW,        /// Raw IP packets
399         IPV6 =  IPPROTO_IPV6,       /// Internet Protocol version 6
400     }
401 }
402 
403 
404 
405 /**
406  * Class for retrieving protocol information.
407  *
408  * Example:
409  * ---
410  * auto proto = new Protocol;
411  * writeln("About protocol TCP:");
412  * if (proto.getProtocolByType(ProtocolType.TCP))
413  * {
414  *     writefln("  Name: %s", proto.name);
415  *     foreach (string s; proto.aliases)
416  *          writefln("  Alias: %s", s);
417  * }
418  * else
419  *     writeln("  No information found");
420  * ---
421  */
422 // class Protocol
423 // {
424 //     /// These members are populated when one of the following functions are called successfully:
425 //     ProtocolType type;
426 //     string name;                /// ditto
427 //     string[] aliases;           /// ditto
428 
429 
430 //     void populate(protoent* proto) @system pure nothrow
431 //     {
432 //         type = cast(ProtocolType) proto.p_proto;
433 //         name = to!string(proto.p_name);
434 
435 //         int i;
436 //         for (i = 0;; i++)
437 //         {
438 //             if (!proto.p_aliases[i])
439 //                 break;
440 //         }
441 
442 //         if (i)
443 //         {
444 //             aliases = new string[i];
445 //             for (i = 0; i != aliases.length; i++)
446 //             {
447 //                 aliases[i] =
448 //                     to!string(proto.p_aliases[i]);
449 //             }
450 //         }
451 //         else
452 //         {
453 //             aliases = null;
454 //         }
455 //     }
456 
457 //     /** Returns: false on failure */
458 //     bool getProtocolByName(scope const(char)[] name) @trusted nothrow
459 //     {
460 //         protoent* proto;
461 //         proto = getprotobyname(name.tempCString());
462 //         if (!proto)
463 //             return false;
464 //         populate(proto);
465 //         return true;
466 //     }
467 
468 
469 //     /** Returns: false on failure */
470 //     // Same as getprotobynumber().
471 //     bool getProtocolByType(ProtocolType type) @trusted nothrow
472 //     {
473 //         protoent* proto;
474 //         proto = getprotobynumber(type);
475 //         if (!proto)
476 //             return false;
477 //         populate(proto);
478 //         return true;
479 //     }
480 // }
481 
482 
483 
484 /**
485  * Class for retrieving service information.
486  *
487  * Example:
488  * ---
489  * auto serv = new Service;
490  * writeln("About service epmap:");
491  * if (serv.getServiceByName("epmap", "tcp"))
492  * {
493  *     writefln("  Service: %s", serv.name);
494  *     writefln("  Port: %d", serv.port);
495  *     writefln("  Protocol: %s", serv.protocolName);
496  *     foreach (string s; serv.aliases)
497  *          writefln("  Alias: %s", s);
498  * }
499  * else
500  *     writefln("  No service for epmap.");
501  * ---
502  */
503 class Service
504 {
505     /// These members are populated when one of the following functions are called successfully:
506     string name;
507     string[] aliases;           /// ditto
508     ushort port;                /// ditto
509     string protocolName;        /// ditto
510 
511 
512     void populate(servent* serv) @system pure nothrow
513     {
514         name = to!string(serv.s_name);
515         port = ntohs(cast(ushort) serv.s_port);
516         protocolName = to!string(serv.s_proto);
517 
518         int i;
519         for (i = 0;; i++)
520         {
521             if (!serv.s_aliases[i])
522                 break;
523         }
524 
525         if (i)
526         {
527             aliases = new string[i];
528             for (i = 0; i != aliases.length; i++)
529             {
530                 aliases[i] =
531                     to!string(serv.s_aliases[i]);
532             }
533         }
534         else
535         {
536             aliases = null;
537         }
538     }
539 
540     /**
541      * If a protocol name is omitted, any protocol will be matched.
542      * Returns: false on failure.
543      */
544     bool getServiceByName(scope const(char)[] name, scope const(char)[] protocolName = null) @trusted nothrow
545     {
546         servent* serv;
547         serv = getservbyname(name.tempCString(), protocolName.tempCString());
548         if (!serv)
549             return false;
550         populate(serv);
551         return true;
552     }
553 
554 
555     /// ditto
556     bool getServiceByPort(ushort port, scope const(char)[] protocolName = null) @trusted nothrow
557     {
558         servent* serv;
559         serv = getservbyport(port, protocolName.tempCString());
560         if (!serv)
561             return false;
562         populate(serv);
563         return true;
564     }
565 }
566 
567 
568 
569 private mixin template socketOSExceptionCtors()
570 {
571     ///
572     this(string msg, string file = __FILE__, size_t line = __LINE__,
573          Throwable next = null, int err = _lasterr())
574     {
575         super(msg, file, line, next, err);
576     }
577 
578     ///
579     this(string msg, Throwable next, string file = __FILE__,
580          size_t line = __LINE__, int err = _lasterr())
581     {
582         super(msg, next, file, line, err);
583     }
584 
585     ///
586     this(string msg, int err, string file = __FILE__, size_t line = __LINE__,
587          Throwable next = null)
588     {
589         super(msg, next, file, line, err);
590     }
591 }
592 
593 
594 /**
595  * Class for exceptions thrown from an `InternetHost`.
596  */
597 class HostException: SocketOSException
598 {
599     mixin socketOSExceptionCtors;
600 }
601 
602 /**
603  * Class for resolving IPv4 addresses.
604  *
605  * Consider using `getAddress`, `parseAddress` and `Address` methods
606  * instead of using this class directly.
607  */
608 class InternetHost
609 {
610     /// These members are populated when one of the following functions are called successfully:
611     string name;
612     string[] aliases;           /// ditto
613     uint[] addrList;            /// ditto
614 
615 
616     void validHostent(in hostent* he)
617     {
618         if (he.h_addrtype != cast(int) AddressFamily.INET || he.h_length != 4)
619             throw new HostException("Address family mismatch");
620     }
621 
622 
623     void populate(hostent* he) @system pure nothrow
624     {
625         int i;
626         char* p;
627 
628         name = to!string(he.h_name);
629 
630         for (i = 0;; i++)
631         {
632             p = he.h_aliases[i];
633             if (!p)
634                 break;
635         }
636 
637         if (i)
638         {
639             aliases = new string[i];
640             for (i = 0; i != aliases.length; i++)
641             {
642                 aliases[i] =
643                     to!string(he.h_aliases[i]);
644             }
645         }
646         else
647         {
648             aliases = null;
649         }
650 
651         for (i = 0;; i++)
652         {
653             p = he.h_addr_list[i];
654             if (!p)
655                 break;
656         }
657 
658         if (i)
659         {
660             addrList = new uint[i];
661             for (i = 0; i != addrList.length; i++)
662             {
663                 addrList[i] = ntohl(*(cast(uint*) he.h_addr_list[i]));
664             }
665         }
666         else
667         {
668             addrList = null;
669         }
670     }
671 
672     private bool getHostNoSync(string opMixin, T)(T param) @system
673     {
674         mixin(opMixin);
675         if (!he)
676             return false;
677         validHostent(he);
678         populate(he);
679         return true;
680     }
681 
682     version (Windows)
683         alias getHost = getHostNoSync;
684     else
685     {
686         // posix systems use global state for return value, so we
687         // must synchronize across all threads
688         private bool getHost(string opMixin, T)(T param) @system
689         {
690             // synchronized(this.classinfo)
691             return getHostNoSync!(opMixin, T)(param);
692         }
693     }
694 
695     /**
696      * Resolve host name.
697      * Returns: false if unable to resolve.
698      */
699     bool getHostByName(scope const(char)[] name) @trusted
700     {
701         static if (is(typeof(gethostbyname_r)))
702         {
703             return getHostNoSync!q{
704                 hostent he_v;
705                 hostent* he;
706                 ubyte[256] buffer_v = void;
707                 auto buffer = buffer_v[];
708                 auto param_zTmp = param.tempCString();
709                 while (true)
710                 {
711                     he = &he_v;
712                     int errno;
713                     if (gethostbyname_r(param_zTmp, he, buffer.ptr, buffer.length, &he, &errno) == ERANGE)
714                         buffer.length = buffer.length * 2;
715                     else
716                         break;
717                 }
718             }(name);
719         }
720         else
721         {
722             return getHost!q{
723                 auto he = gethostbyname(param.tempCString());
724             }(name);
725         }
726     }
727 
728     /**
729      * Resolve IPv4 address number.
730      *
731      * Params:
732      *   addr = The IPv4 address to resolve, in host byte order.
733      * Returns:
734      *   false if unable to resolve.
735      */
736     bool getHostByAddr(uint addr) @trusted
737     {
738         return getHost!q{
739             auto x = htonl(param);
740             auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
741         }(addr);
742     }
743 
744     /**
745      * Same as previous, but addr is an IPv4 address string in the
746      * dotted-decimal form $(I a.b.c.d).
747      * Returns: false if unable to resolve.
748      */
749     bool getHostByAddr(scope const(char)[] addr) @trusted
750     {
751         return getHost!q{
752             auto x = inet_addr(param.tempCString());
753             enforce(x != INADDR_NONE,
754                 new SocketParameterException("Invalid IPv4 address"));
755             auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
756         }(addr);
757     }
758 }
759 
760 ///
761 
762 
763 
764 /// Holds information about a socket _address retrieved by `getAddressInfo`.
765 struct AddressInfo
766 {
767     AddressFamily family;   /// Address _family
768     SocketType type;        /// Socket _type
769     ProtocolType protocol;  /// Protocol
770     Address address;        /// Socket _address
771     string canonicalName;   /// Canonical name, when `AddressInfoFlags.CANONNAME` is used.
772 }
773 
774 /**
775  * A subset of flags supported on all platforms with getaddrinfo.
776  * Specifies option flags for `getAddressInfo`.
777  */
778 enum AddressInfoFlags: int
779 {
780     /// The resulting addresses will be used in a call to `Socket.bind`.
781     PASSIVE = AI_PASSIVE,
782 
783     /// The canonical name is returned in `canonicalName` member in the first `AddressInfo`.
784     CANONNAME = AI_CANONNAME,
785 
786     /**
787      * The `node` parameter passed to `getAddressInfo` must be a numeric string.
788      * This will suppress any potentially lengthy network host address lookups.
789      */
790     NUMERICHOST = AI_NUMERICHOST,
791 }
792 
793 
794 /**
795  * On POSIX, getaddrinfo uses its own error codes, and thus has its own
796  * formatting function.
797  */
798 private string formatGaiError(int err) @trusted
799 {
800     version (Windows)
801     {
802         return generateSysErrorMsg(err);
803     }
804     else
805     {
806         // synchronized
807             return to!string(gai_strerror(err));
808     }
809 }
810 
811 /**
812  * Provides _protocol-independent translation from host names to socket
813  * addresses. If advanced functionality is not required, consider using
814  * `getAddress` for compatibility with older systems.
815  *
816  * Returns: Array with one `AddressInfo` per socket address.
817  *
818  * Throws: `SocketOSException` on failure, or `SocketFeatureException`
819  * if this functionality is not available on the current system.
820  *
821  * Params:
822  *  node     = string containing host name or numeric address
823  *  options  = optional additional parameters, identified by type:
824  *             $(UL $(LI `string` - service name or port number)
825  *                  $(LI `AddressInfoFlags` - option flags)
826  *                  $(LI `AddressFamily` - address family to filter by)
827  *                  $(LI `SocketType` - socket type to filter by)
828  *                  $(LI `ProtocolType` - protocol to filter by))
829  *
830  * Example:
831  * ---
832  * // Roundtrip DNS resolution
833  * auto results = getAddressInfo("www.digitalmars.com");
834  * assert(results[0].address.toHostNameString() ==
835  *     "digitalmars.com");
836  *
837  * // Canonical name
838  * results = getAddressInfo("www.digitalmars.com",
839  *     AddressInfoFlags.CANONNAME);
840  * assert(results[0].canonicalName == "digitalmars.com");
841  *
842  * // IPv6 resolution
843  * results = getAddressInfo("ipv6.google.com");
844  * assert(results[0].family == AddressFamily.INET6);
845  *
846  * // Multihomed resolution
847  * results = getAddressInfo("google.com");
848  * assert(results.length > 1);
849  *
850  * // Parsing IPv4
851  * results = getAddressInfo("127.0.0.1",
852  *     AddressInfoFlags.NUMERICHOST);
853  * assert(results.length && results[0].family ==
854  *     AddressFamily.INET);
855  *
856  * // Parsing IPv6
857  * results = getAddressInfo("::1",
858  *     AddressInfoFlags.NUMERICHOST);
859  * assert(results.length && results[0].family ==
860  *     AddressFamily.INET6);
861  * ---
862  */
863 AddressInfo[] getAddressInfo(T...)(scope const(char)[] node, scope T options)
864 {
865     const(char)[] service = null;
866     addrinfo hints;
867     hints.ai_family = AF_UNSPEC;
868 
869     foreach (i, option; options)
870     {
871         static if (is(typeof(option) : const(char)[]))
872             service = options[i];
873         else
874         static if (is(typeof(option) == AddressInfoFlags))
875             hints.ai_flags |= option;
876         else
877         static if (is(typeof(option) == AddressFamily))
878             hints.ai_family = option;
879         else
880         static if (is(typeof(option) == SocketType))
881             hints.ai_socktype = option;
882         else
883         static if (is(typeof(option) == ProtocolType))
884             hints.ai_protocol = option;
885         else
886             static assert(0, "Unknown getAddressInfo option type: " ~ typeof(option).stringof);
887     }
888 
889     return () @trusted { return getAddressInfoImpl(node, service, &hints); }();
890 }
891 
892 
893 private AddressInfo[] getAddressInfoImpl(scope const(char)[] node, scope const(char)[] service, addrinfo* hints) @system
894 {
895 
896     if (getaddrinfoPointer && freeaddrinfoPointer)
897     {
898         addrinfo* ai_res;
899 
900         int ret = getaddrinfoPointer(
901             node.tempCString(),
902             service.tempCString(),
903             hints, &ai_res);
904         enforce(ret == 0, new SocketOSException("getaddrinfo error", ret, &formatGaiError));
905         scope(exit) freeaddrinfoPointer(ai_res);
906 
907         AddressInfo[] result;
908 
909         // Use const to force UnknownAddressReference to copy the sockaddr.
910         for (const(addrinfo)* ai = ai_res; ai; ai = ai.ai_next)
911             result ~= AddressInfo(
912                 cast(AddressFamily) ai.ai_family,
913                 cast(SocketType   ) ai.ai_socktype,
914                 cast(ProtocolType ) ai.ai_protocol,
915                 new UnknownAddressReference(ai.ai_addr, cast(socklen_t) ai.ai_addrlen),
916                 ai.ai_canonname ? to!string(ai.ai_canonname) : null);
917 
918         return result;
919     }
920 
921     throw new SocketFeatureException("Address info lookup is not available " ~
922         "on this system.");
923 }
924 
925 
926 
927 private ushort serviceToPort(scope const(char)[] service)
928 {
929     if (service == "")
930         return InternetAddress.PORT_ANY;
931     else
932     if (isNumber(service))
933         return to!ushort(service);
934     else
935     {
936         auto s = new Service();
937         s.getServiceByName(service);
938         return s.port;
939     }
940 }
941 
942 /**
943  * Provides _protocol-independent translation from host names to socket
944  * addresses. Uses `getAddressInfo` if the current system supports it,
945  * and `InternetHost` otherwise.
946  *
947  * Returns: Array with one `Address` instance per socket address.
948  *
949  * Throws: `SocketOSException` on failure.
950  *
951  * Example:
952  * ---
953  * writeln("Resolving www.digitalmars.com:");
954  * try
955  * {
956  *     auto addresses = getAddress("www.digitalmars.com");
957  *     foreach (address; addresses)
958  *         writefln("  IP: %s", address.toAddrString());
959  * }
960  * catch (SocketException e)
961  *     writefln("  Lookup failed: %s", e.msg);
962  * ---
963  */
964 Address[] getAddress(scope const(char)[] hostname, scope const(char)[] service = null)
965 {
966     if (getaddrinfoPointer && freeaddrinfoPointer)
967     {
968         // use getAddressInfo
969         auto infos = getAddressInfo(hostname, service);
970         Address[] results;
971         results.length = infos.length;
972         foreach (i, ref result; results)
973             result = infos[i].address;
974         return results;
975     }
976     else
977         return getAddress(hostname, serviceToPort(service));
978 }
979 
980 /// ditto
981 Address[] getAddress(scope const(char)[] hostname, ushort port)
982 {
983     if (getaddrinfoPointer && freeaddrinfoPointer)
984         return getAddress(hostname, to!string(port));
985     else
986     {
987         // use getHostByName
988         auto ih = new InternetHost;
989         if (!ih.getHostByName(hostname))
990         {
991             throw new AddressException(
992                         cast(string)("Unable to resolve host '" ~hostname.idup ~"'"));
993         }
994 
995         Address[] results;
996         foreach (uint addr; ih.addrList)
997             results ~= new InternetAddress(addr, port);
998         return results;
999     }
1000 }
1001 
1002 
1003 
1004 
1005 
1006 /**
1007  * Provides _protocol-independent parsing of network addresses. Does not
1008  * attempt name resolution. Uses `getAddressInfo` with
1009  * `AddressInfoFlags.NUMERICHOST` if the current system supports it, and
1010  * `InternetAddress` otherwise.
1011  *
1012  * Returns: An `Address` instance representing specified address.
1013  *
1014  * Throws: `SocketException` on failure.
1015  *
1016  * Example:
1017  * ---
1018  * writeln("Enter IP address:");
1019  * string ip = readln().chomp();
1020  * try
1021  * {
1022  *     Address address = parseAddress(ip);
1023  *     writefln("Looking up reverse of %s:",
1024  *         address.toAddrString());
1025  *     try
1026  *     {
1027  *         string reverse = address.toHostNameString();
1028  *         if (reverse)
1029  *             writefln("  Reverse name: %s", reverse);
1030  *         else
1031  *             writeln("  Reverse hostname not found.");
1032  *     }
1033  *     catch (SocketException e)
1034  *         writefln("  Lookup error: %s", e.msg);
1035  * }
1036  * catch (SocketException e)
1037  * {
1038  *     writefln("  %s is not a valid IP address: %s",
1039  *         ip, e.msg);
1040  * }
1041  * ---
1042  */
1043 Address parseAddress(scope const(char)[] hostaddr, scope const(char)[] service = null)
1044 {
1045     if (getaddrinfoPointer && freeaddrinfoPointer)
1046         return getAddressInfo(hostaddr, service, AddressInfoFlags.NUMERICHOST)[0].address;
1047     else
1048         return parseAddress(hostaddr, serviceToPort(service));
1049 }
1050 
1051 /// ditto
1052 Address parseAddress(scope const(char)[] hostaddr, ushort port)
1053 {
1054     if (getaddrinfoPointer && freeaddrinfoPointer)
1055         return parseAddress(hostaddr, to!string(port));
1056     else
1057     {
1058         auto in4_addr = InternetAddress.parse(hostaddr);
1059         enforce(in4_addr != InternetAddress.ADDR_NONE,
1060             new SocketParameterException("Invalid IP address"));
1061         return new InternetAddress(in4_addr, port);
1062     }
1063 }
1064 
1065 
1066 
1067 /**
1068  * Class for exceptions thrown from an `Address`.
1069  */
1070 class AddressException: SocketOSException
1071 {
1072     mixin socketOSExceptionCtors;
1073 }
1074 
1075 
1076 /**
1077  * Abstract class for representing a socket address.
1078  *
1079  * Example:
1080  * ---
1081  * writeln("About www.google.com port 80:");
1082  * try
1083  * {
1084  *     Address[] addresses = getAddress("www.google.com", 80);
1085  *     writefln("  %d addresses found.", addresses.length);
1086  *     foreach (int i, Address a; addresses)
1087  *     {
1088  *         writefln("  Address %d:", i+1);
1089  *         writefln("    IP address: %s", a.toAddrString());
1090  *         writefln("    Hostname: %s", a.toHostNameString());
1091  *         writefln("    Port: %s", a.toPortString());
1092  *         writefln("    Service name: %s",
1093  *             a.toServiceNameString());
1094  *     }
1095  * }
1096  * catch (SocketException e)
1097  *     writefln("  Lookup error: %s", e.msg);
1098  * ---
1099  */
1100 abstract class Address
1101 {
1102     /// Returns pointer to underlying `sockaddr` structure.
1103     abstract @property sockaddr* name() pure nothrow @nogc;
1104     abstract @property const(sockaddr)* name() const pure nothrow @nogc; /// ditto
1105 
1106     /// Returns actual size of underlying `sockaddr` structure.
1107     abstract @property socklen_t nameLen() const pure nothrow @nogc;
1108 
1109     // Socket.remoteAddress, Socket.localAddress, and Socket.receiveFrom
1110     // use setNameLen to set the actual size of the address as returned by
1111     // getsockname, getpeername, and recvfrom, respectively.
1112     // The following implementation is sufficient for fixed-length addresses,
1113     // and ensures that the length is not changed.
1114     // Must be overridden for variable-length addresses.
1115     protected void setNameLen(socklen_t len)
1116     {
1117         if (len != this.nameLen)
1118             throw new AddressException(typeid(this).toString ~ " expects address of length "~nameLen.to!string~", not "~len.to!string, 0);
1119     }
1120 
1121     /// Family of this address.
1122     @property AddressFamily addressFamily() const pure nothrow @nogc
1123     {
1124         return cast(AddressFamily) name.sa_family;
1125     }
1126 
1127     // Common code for toAddrString and toHostNameString
1128     private string toHostString(bool numeric) @trusted const
1129     {
1130         // getnameinfo() is the recommended way to perform a reverse (name)
1131         // lookup on both Posix and Windows. However, it is only available
1132         // on Windows XP and above, and not included with the WinSock import
1133         // libraries shipped with DMD. Thus, we check for getnameinfo at
1134         // runtime in the shared module constructor, and use it if it's
1135         // available in the base class method. Classes for specific network
1136         // families (e.g. InternetHost) override this method and use a
1137         // deprecated, albeit commonly-available method when getnameinfo()
1138         // is not available.
1139         // http://technet.microsoft.com/en-us/library/aa450403.aspx
1140 
1141         throw new SocketFeatureException((numeric ? "Host address" : "Host name") ~
1142             " lookup for this address family is not available on this system.");
1143     }
1144 
1145     // Common code for toPortString and toServiceNameString
1146     private string toServiceString(bool numeric) @trusted const
1147     {
1148         // See toHostNameString() for details about getnameinfo().
1149 
1150         throw new SocketFeatureException((numeric ? "Port number" : "Service name") ~
1151             " lookup for this address family is not available on this system.");
1152     }
1153 
1154     /**
1155      * Attempts to retrieve the host address as a human-readable string.
1156      *
1157      * Throws: `AddressException` on failure, or `SocketFeatureException`
1158      * if address retrieval for this address family is not available on the
1159      * current system.
1160      */
1161     string toAddrString() const
1162     {
1163         return toHostString(true);
1164     }
1165 
1166     /**
1167      * Attempts to retrieve the host name as a fully qualified domain name.
1168      *
1169      * Returns: The FQDN corresponding to this `Address`, or `null` if
1170      * the host name did not resolve.
1171      *
1172      * Throws: `AddressException` on error, or `SocketFeatureException`
1173      * if host name lookup for this address family is not available on the
1174      * current system.
1175      */
1176     string toHostNameString() const
1177     {
1178         return toHostString(false);
1179     }
1180 
1181     /**
1182      * Attempts to retrieve the numeric port number as a string.
1183      *
1184      * Throws: `AddressException` on failure, or `SocketFeatureException`
1185      * if port number retrieval for this address family is not available on the
1186      * current system.
1187      */
1188     string toPortString() const
1189     {
1190         return toServiceString(true);
1191     }
1192 
1193     /**
1194      * Attempts to retrieve the service name as a string.
1195      *
1196      * Throws: `AddressException` on failure, or `SocketFeatureException`
1197      * if service name lookup for this address family is not available on the
1198      * current system.
1199      */
1200     string toServiceNameString() const
1201     {
1202         return toServiceString(false);
1203     }
1204 
1205     /// Human readable string representing this address.
1206     override string toString() const
1207     {
1208         try
1209         {
1210             string host = toAddrString();
1211             string port = toPortString();
1212             if (host.indexOf(":") >= 0)
1213                 return "[" ~ host ~ "]:" ~ port;
1214             else
1215                 return host ~ ":" ~ port;
1216         }
1217         catch (SocketException)
1218             return "Unknown";
1219     }
1220 }
1221 
1222 /**
1223  * Encapsulates an unknown socket address.
1224  */
1225 class UnknownAddress: Address
1226 {
1227 protected:
1228     sockaddr sa;
1229 
1230 
1231 public:
1232     override @property sockaddr* name() return
1233     {
1234         return &sa;
1235     }
1236 
1237     override @property const(sockaddr)* name() const return
1238     {
1239         return &sa;
1240     }
1241 
1242 
1243     override @property socklen_t nameLen() const
1244     {
1245         return cast(socklen_t) sa.sizeof;
1246     }
1247 
1248 }
1249 
1250 
1251 /**
1252  * Encapsulates a reference to an arbitrary
1253  * socket address.
1254  */
1255 class UnknownAddressReference: Address
1256 {
1257 protected:
1258     sockaddr* sa;
1259     socklen_t len;
1260 
1261 public:
1262     /// Constructs an `Address` with a reference to the specified `sockaddr`.
1263     this(sockaddr* sa, socklen_t len) pure nothrow @nogc
1264     {
1265         this.sa  = sa;
1266         this.len = len;
1267     }
1268 
1269     /// Constructs an `Address` with a copy of the specified `sockaddr`.
1270     this(const(sockaddr)* sa, socklen_t len) @system pure nothrow
1271     {
1272         this.sa = cast(sockaddr*) (cast(ubyte*) sa)[0 .. len].dup.ptr;
1273         this.len = len;
1274     }
1275 
1276     override @property sockaddr* name()
1277     {
1278         return sa;
1279     }
1280 
1281     override @property const(sockaddr)* name() const
1282     {
1283         return sa;
1284     }
1285 
1286 
1287     override @property socklen_t nameLen() const
1288     {
1289         return cast(socklen_t) len;
1290     }
1291 }
1292 
1293 
1294 /**
1295  * Encapsulates an IPv4 (Internet Protocol version 4) socket address.
1296  *
1297  * Consider using `getAddress`, `parseAddress` and `Address` methods
1298  * instead of using this class directly.
1299  */
1300 class InternetAddress: Address
1301 {
1302 protected:
1303     sockaddr_in sin;
1304 
1305 
1306     this() pure nothrow @nogc
1307     {
1308     }
1309 
1310 
1311 public:
1312     override @property sockaddr* name() return
1313     {
1314         return cast(sockaddr*)&sin;
1315     }
1316 
1317     override @property const(sockaddr)* name() const return
1318     {
1319         return cast(const(sockaddr)*)&sin;
1320     }
1321 
1322 
1323     override @property socklen_t nameLen() const
1324     {
1325         return cast(socklen_t) sin.sizeof;
1326     }
1327 
1328 
1329     enum uint ADDR_ANY = INADDR_ANY;         /// Any IPv4 host address.
1330     enum uint ADDR_NONE = INADDR_NONE;       /// An invalid IPv4 host address.
1331     enum ushort PORT_ANY = 0;                /// Any IPv4 port number.
1332 
1333     /// Returns the IPv4 _port number (in host byte order).
1334     @property ushort port() const pure nothrow @nogc
1335     {
1336         return ntohs(sin.sin_port);
1337     }
1338 
1339     /// Returns the IPv4 address number (in host byte order).
1340     @property uint addr() const pure nothrow @nogc
1341     {
1342         return ntohl(sin.sin_addr.s_addr);
1343     }
1344 
1345     /**
1346      * Construct a new `InternetAddress`.
1347      * Params:
1348      *   addr = an IPv4 address string in the dotted-decimal form a.b.c.d,
1349      *          or a host name which will be resolved using an `InternetHost`
1350      *          object.
1351      *   port = port number, may be `PORT_ANY`.
1352      */
1353     this(scope const(char)[] addr, ushort port)
1354     {
1355         uint uiaddr = parse(addr);
1356         if (ADDR_NONE == uiaddr)
1357         {
1358             InternetHost ih = new InternetHost;
1359             if (!ih.getHostByName(addr))
1360                 //throw new AddressException("Invalid internet address");
1361                 throw new AddressException(
1362                           "Unable to resolve host '"~ addr.idup~ "'");
1363             uiaddr = ih.addrList[0];
1364         }
1365         sin.sin_family = AddressFamily.INET;
1366         sin.sin_addr.s_addr = htonl(uiaddr);
1367         sin.sin_port = htons(port);
1368     }
1369 
1370     /**
1371      * Construct a new `InternetAddress`.
1372      * Params:
1373      *   addr = (optional) an IPv4 address in host byte order, may be `ADDR_ANY`.
1374      *   port = port number, may be `PORT_ANY`.
1375      */
1376     this(uint addr, ushort port) pure nothrow @nogc
1377     {
1378         sin.sin_family = AddressFamily.INET;
1379         sin.sin_addr.s_addr = htonl(addr);
1380         sin.sin_port = htons(port);
1381     }
1382 
1383     /// ditto
1384     this(ushort port) pure nothrow @nogc
1385     {
1386         sin.sin_family = AddressFamily.INET;
1387         sin.sin_addr.s_addr = ADDR_ANY;
1388         sin.sin_port = htons(port);
1389     }
1390 
1391     /**
1392      * Construct a new `InternetAddress`.
1393      * Params:
1394      *   addr = A sockaddr_in as obtained from lower-level API calls such as getifaddrs.
1395      */
1396     this(sockaddr_in addr) pure nothrow @nogc
1397     {
1398         assert(addr.sin_family == AddressFamily.INET, "Socket address is not of INET family.");
1399         sin = addr;
1400     }
1401 
1402     /// Human readable string representing the IPv4 address in dotted-decimal form.
1403     override string toAddrString() @trusted const
1404     {
1405         return to!string(inet_ntoa(sin.sin_addr));
1406     }
1407 
1408     /// Human readable string representing the IPv4 port.
1409     override string toPortString() const
1410     {
1411         return to!string(port);
1412     }
1413 
1414     /**
1415      * Attempts to retrieve the host name as a fully qualified domain name.
1416      *
1417      * Returns: The FQDN corresponding to this `InternetAddress`, or
1418      * `null` if the host name did not resolve.
1419      *
1420      * Throws: `AddressException` on error.
1421      */
1422     override string toHostNameString() const
1423     {
1424         // getnameinfo() is the recommended way to perform a reverse (name)
1425         // lookup on both Posix and Windows. However, it is only available
1426         // on Windows XP and above, and not included with the WinSock import
1427         // libraries shipped with DMD. Thus, we check for getnameinfo at
1428         // runtime in the shared module constructor, and fall back to the
1429         // deprecated getHostByAddr() if it could not be found. See also:
1430         // http://technet.microsoft.com/en-us/library/aa450403.aspx
1431 
1432         auto host = new InternetHost();
1433         if (!host.getHostByAddr(ntohl(sin.sin_addr.s_addr)))
1434             return null;
1435         return host.name;
1436     }
1437 
1438     /**
1439      * Provides support for comparing equality with another
1440      * InternetAddress of the same type.
1441      * Returns: true if the InternetAddresses share the same address and
1442      * port number.
1443      */
1444     override bool opEquals(Object o) const
1445     {
1446         auto other = cast(InternetAddress) o;
1447         return other && this.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr &&
1448             this.sin.sin_port == other.sin.sin_port;
1449     }
1450 
1451     ///
1452 
1453 
1454     /**
1455      * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
1456      * and return the number.
1457      * Returns: If the string is not a legitimate IPv4 address,
1458      * `ADDR_NONE` is returned.
1459      */
1460     static uint parse(scope const(char)[] addr) @trusted nothrow
1461     {
1462         return ntohl(inet_addr(addr.tempCString()));
1463     }
1464 
1465     /**
1466      * Convert an IPv4 address number in host byte order to a human readable
1467      * string representing the IPv4 address in dotted-decimal form.
1468      */
1469     static string addrToString(uint addr) @trusted nothrow
1470     {
1471         in_addr sin_addr;
1472         sin_addr.s_addr = htonl(addr);
1473         return to!string(inet_ntoa(sin_addr));
1474     }
1475 }
1476 
1477 
1478 
1479 /**
1480  * Encapsulates an IPv6 (Internet Protocol version 6) socket address.
1481  *
1482  * Consider using `getAddress`, `parseAddress` and `Address` methods
1483  * instead of using this class directly.
1484  */
1485 class Internet6Address: Address
1486 {
1487 protected:
1488     sockaddr_in6 sin6;
1489 
1490 
1491     this() pure nothrow @nogc
1492     {
1493     }
1494 
1495 
1496 public:
1497     override @property sockaddr* name() return
1498     {
1499         return cast(sockaddr*)&sin6;
1500     }
1501 
1502     override @property const(sockaddr)* name() const return
1503     {
1504         return cast(const(sockaddr)*)&sin6;
1505     }
1506 
1507 
1508     override @property socklen_t nameLen() const
1509     {
1510         return cast(socklen_t) sin6.sizeof;
1511     }
1512 
1513     __gshared immutable in6_addr in6addr_any = {[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]};
1514 
1515     /// Any IPv6 host address.
1516     static @property ref const(ubyte)[16] ADDR_ANY() pure nothrow @nogc
1517     {
1518         static if (is(typeof(IN6ADDR_ANY)))
1519         {
1520             version (Windows)
1521             {
1522                 static immutable addr = IN6ADDR_ANY.s6_addr;
1523                 return addr;
1524             }
1525             else
1526                 return IN6ADDR_ANY.s6_addr;
1527         }
1528         else static if (is(typeof(in6addr_any)))
1529         {
1530             return in6addr_any.s6_addr;
1531         }
1532         else
1533         {
1534             return in6addr_any;
1535         }
1536     }
1537 
1538     /// Any IPv6 port number.
1539     enum ushort PORT_ANY = 0;
1540 
1541     /// Returns the IPv6 port number.
1542     @property ushort port() const pure nothrow @nogc
1543     {
1544         return ntohs(sin6.sin6_port);
1545     }
1546 
1547     /// Returns the IPv6 address.
1548     @property ubyte[16] addr() const pure nothrow @nogc
1549     {
1550         return sin6.sin6_addr.s6_addr;
1551     }
1552 
1553     /**
1554      * Construct a new `Internet6Address`.
1555      * Params:
1556      *   addr    = an IPv6 host address string in the form described in RFC 2373,
1557      *             or a host name which will be resolved using `getAddressInfo`.
1558      *   service = (optional) service name.
1559      */
1560     this(scope const(char)[] addr, scope const(char)[] service = null) @trusted
1561     {
1562         auto results = getAddressInfo(addr, service, AddressFamily.INET6);
1563         assert(results.length && results[0].family == AddressFamily.INET6);
1564         sin6 = *cast(sockaddr_in6*) results[0].address.name;
1565     }
1566 
1567     /**
1568      * Construct a new `Internet6Address`.
1569      * Params:
1570      *   addr = an IPv6 host address string in the form described in RFC 2373,
1571      *          or a host name which will be resolved using `getAddressInfo`.
1572      *   port = port number, may be `PORT_ANY`.
1573      */
1574     this(scope const(char)[] addr, ushort port)
1575     {
1576         if (port == PORT_ANY)
1577             this(addr);
1578         else
1579             this(addr, to!string(port));
1580     }
1581 
1582     /**
1583      * Construct a new `Internet6Address`.
1584      * Params:
1585      *   addr = (optional) an IPv6 host address in host byte order, or
1586      *          `ADDR_ANY`.
1587      *   port = port number, may be `PORT_ANY`.
1588      */
1589     this(ubyte[16] addr, ushort port) pure nothrow @nogc
1590     {
1591         sin6.sin6_family = AddressFamily.INET6;
1592         sin6.sin6_addr.s6_addr = addr;
1593         sin6.sin6_port = htons(port);
1594     }
1595 
1596     /// ditto
1597     this(ushort port) pure nothrow @nogc
1598     {
1599         sin6.sin6_family = AddressFamily.INET6;
1600         sin6.sin6_addr.s6_addr = ADDR_ANY;
1601         sin6.sin6_port = htons(port);
1602     }
1603 
1604      /**
1605      * Construct a new `Internet6Address`.
1606      * Params:
1607      *   addr = A sockaddr_in6 as obtained from lower-level API calls such as getifaddrs.
1608      */
1609     this(sockaddr_in6 addr) pure nothrow @nogc
1610     {
1611         assert(addr.sin6_family == AddressFamily.INET6);
1612         sin6 = addr;
1613     }
1614 
1615    /**
1616      * Parse an IPv6 host address string as described in RFC 2373, and return the
1617      * address.
1618      * Throws: `SocketException` on error.
1619      */
1620     static ubyte[16] parse(scope const(char)[] addr) @trusted
1621     {
1622         // Although we could use inet_pton here, it's only available on Windows
1623         // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1624         // instead.
1625         auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1626         if (results.length && results[0].family == AddressFamily.INET6)
1627             return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1628         throw new AddressException("Not an IPv6 address", 0);
1629     }
1630 }
1631 
1632 
1633 
1634 version (StdDdoc)
1635 {
1636     static if (!is(sockaddr_un))
1637     {
1638         // This exists only to allow the constructor taking
1639         // a sockaddr_un to be compilable for documentation
1640         // on platforms that don't supply a sockaddr_un.
1641         struct sockaddr_un
1642         {
1643         }
1644     }
1645 
1646     /**
1647      * Encapsulates an address for a Unix domain socket (`AF_UNIX`),
1648      * i.e. a socket bound to a path name in the file system.
1649      * Available only on supported systems.
1650      *
1651      * Linux also supports an abstract address namespace, in which addresses
1652      * are independent of the file system. A socket address is abstract
1653      * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1654      * positions of an abstract address are allowed and have no special
1655      * meaning.
1656      *
1657      * Example:
1658      * ---
1659      * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1660      * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1661      * ---
1662      *
1663      * See_Also: $(HTTP man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1664      */
1665     class UnixAddress: Address
1666     {
1667         private this() pure nothrow @nogc {}
1668 
1669         /// Construct a new `UnixAddress` from the specified path.
1670         this(scope const(char)[] path) { }
1671 
1672         /**
1673          * Construct a new `UnixAddress`.
1674          * Params:
1675          *   addr = A sockaddr_un as obtained from lower-level API calls.
1676          */
1677         this(sockaddr_un addr) pure nothrow @nogc { }
1678 
1679         /// Get the underlying _path.
1680         @property string path() const { return null; }
1681 
1682         /// ditto
1683         override string toString() const { return null; }
1684 
1685         override @property sockaddr* name() { return null; }
1686         override @property const(sockaddr)* name() const { return null; }
1687         override @property socklen_t nameLen() const { return 0; }
1688     }
1689 }
1690 else
1691 static if (is(sockaddr_un))
1692 {
1693     class UnixAddress: Address
1694     {
1695     protected:
1696         socklen_t _nameLen;
1697 
1698         struct
1699         {
1700         align (1):
1701             sockaddr_un sun;
1702             char unused = '\0'; // placeholder for a terminating '\0'
1703         }
1704 
1705         this() pure nothrow @nogc
1706         {
1707             sun.sun_family = AddressFamily.UNIX;
1708             sun.sun_path = '?';
1709             _nameLen = sun.sizeof;
1710         }
1711 
1712         override void setNameLen(socklen_t len) @trusted
1713         {
1714             if (len > sun.sizeof)
1715                 throw new SocketParameterException("Not enough socket address storage");
1716             _nameLen = len;
1717         }
1718 
1719     public:
1720         override @property sockaddr* name() return
1721         {
1722             return cast(sockaddr*)&sun;
1723         }
1724 
1725         override @property const(sockaddr)* name() const return
1726         {
1727             return cast(const(sockaddr)*)&sun;
1728         }
1729 
1730         override @property socklen_t nameLen() @trusted const
1731         {
1732             return _nameLen;
1733         }
1734 
1735         this(scope const(char)[] path) @trusted pure
1736         {
1737             enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
1738             sun.sun_family = AddressFamily.UNIX;
1739             sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
1740             _nameLen = cast(socklen_t)
1741                 {
1742                     auto len = sockaddr_un.init.sun_path.offsetof + path.length;
1743                     // Pathname socket address must be terminated with '\0'
1744                     // which must be included in the address length.
1745                     if (sun.sun_path.ptr[0])
1746                     {
1747                         sun.sun_path.ptr[path.length] = 0;
1748                         ++len;
1749                     }
1750                     return len;
1751                 }();
1752         }
1753 
1754         this(sockaddr_un addr) pure nothrow @nogc
1755         {
1756             assert(addr.sun_family == AddressFamily.UNIX);
1757             sun = addr;
1758         }
1759 
1760         @property string path() @trusted const pure
1761         {
1762             auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
1763             if (len == 0)
1764                 return null; // An empty path may be returned from getpeername
1765             // For pathname socket address we need to strip off the terminating '\0'
1766             if (sun.sun_path.ptr[0])
1767                 --len;
1768             return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
1769         }
1770 
1771         override string toString() const pure
1772         {
1773             return path;
1774         }
1775     }
1776 
1777 }
1778 
1779 
1780 /**
1781  * Exception thrown by `Socket.accept`.
1782  */
1783 class SocketAcceptException: SocketOSException
1784 {
1785     mixin socketOSExceptionCtors;
1786 }
1787 
1788 /// How a socket is shutdown:
1789 enum SocketShutdown: int
1790 {
1791     RECEIVE =  SD_RECEIVE,      /// socket receives are disallowed
1792     SEND =     SD_SEND,         /// socket sends are disallowed
1793     BOTH =     SD_BOTH,         /// both RECEIVE and SEND
1794 }
1795 
1796 
1797 /// Socket flags that may be OR'ed together:
1798 enum SocketFlags: int
1799 {
1800     NONE =       0,                 /// no flags specified
1801 
1802     OOB =        MSG_OOB,           /// out-of-band stream data
1803     PEEK =       MSG_PEEK,          /// peek at incoming data without removing it from the queue, only for receiving
1804     DONTROUTE =  MSG_DONTROUTE,     /// data should not be subject to routing; this flag may be ignored. Only for sending
1805 }
1806 
1807 import core.stdc.time:time_t;
1808 
1809 struct timeval
1810 {
1811     time_t  tv_sec;
1812     long    tv_usec;
1813 }
1814 
1815 
1816 // /// Duration timeout value.
1817 struct TimeVal
1818 {
1819     timeval ctimeval;
1820     alias tv_sec_t = typeof(ctimeval.tv_sec);
1821     alias tv_usec_t = typeof(ctimeval.tv_usec);
1822 
1823     /// Number of _seconds.
1824     pure nothrow @nogc @property
1825     ref inout(tv_sec_t) seconds() inout return
1826     {
1827         return ctimeval.tv_sec;
1828     }
1829 
1830     /// Number of additional _microseconds.
1831     pure nothrow @nogc @property
1832     ref inout(tv_usec_t) microseconds() inout return
1833     {
1834         return ctimeval.tv_usec;
1835     }
1836 }
1837 
1838 
1839 /**
1840  * A collection of sockets for use with `Socket.select`.
1841  *
1842  * `SocketSet` wraps the platform `fd_set` type. However, unlike
1843  * `fd_set`, `SocketSet` is not statically limited to `FD_SETSIZE`
1844  * or any other limit, and grows as needed.
1845  */
1846 class SocketSet
1847 {
1848 private:
1849     version (Windows)
1850     {
1851         // On Windows, fd_set is an array of socket handles,
1852         // following a word containing the fd_set instance size.
1853         // We use one dynamic array for everything, and use its first
1854         // element(s) for the count.
1855 
1856         alias fd_set_count_type = typeof(fd_set.init.fd_count);
1857         alias fd_set_type = typeof(fd_set.init.fd_array[0]);
1858         static assert(fd_set_type.sizeof == socket_t.sizeof);
1859 
1860         // Number of fd_set_type elements at the start of our array that are
1861         // used for the socket count and alignment
1862 
1863         enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
1864         static assert(FD_SET_OFFSET);
1865         static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
1866 
1867         fd_set_type[] set;
1868 
1869         void resize(size_t size) pure nothrow
1870         {
1871             set.length = FD_SET_OFFSET + size;
1872         }
1873 
1874         ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
1875         {
1876             assert(set.length);
1877             return *cast(inout(fd_set_count_type)*)set.ptr;
1878         }
1879 
1880         size_t capacity() @property const pure nothrow @nogc
1881         {
1882             return set.length - FD_SET_OFFSET;
1883         }
1884 
1885         inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
1886         {
1887             return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
1888         }
1889     }
1890     else
1891     version (LinuxLike)
1892     {
1893         // On Posix, fd_set is a bit array. We assume that the fd_set
1894         // type (declared in core.sys.posix.sys.select) is a structure
1895         // containing a single field, a static array.
1896 
1897         static assert(fd_set.tupleof.length == 1);
1898 
1899         // This is the type used in the fd_set array.
1900         // Using the type of the correct size is important for big-endian
1901         // architectures.
1902 
1903         alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
1904 
1905         // Number of file descriptors represented by one fd_set_type
1906 
1907         enum FD_NFDBITS = 8 * fd_set_type.sizeof;
1908 
1909         static fd_set_type mask(uint n) pure nothrow @nogc
1910         {
1911             return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
1912         }
1913 
1914         // Array size to fit that many sockets
1915 
1916         static size_t lengthFor(size_t size) pure nothrow @nogc
1917         {
1918             return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
1919         }
1920 
1921         fd_set_type[] set;
1922 
1923         void resize(size_t size) pure nothrow
1924         {
1925             set.length = lengthFor(size);
1926         }
1927 
1928         // Make sure we can fit that many sockets
1929 
1930         void setMinCapacity(size_t size) pure nothrow
1931         {
1932             auto length = lengthFor(size);
1933             if (set.length < length)
1934                 set.length = length;
1935         }
1936 
1937         size_t capacity() @property const pure nothrow @nogc
1938         {
1939             return set.length * FD_NFDBITS;
1940         }
1941 
1942         int maxfd;
1943     }
1944     else
1945         static assert(false, "Unknown platform");
1946 
1947 public:
1948 
1949     /**
1950      * Create a SocketSet with a specific initial capacity (defaults to
1951      * `FD_SETSIZE`, the system's default capacity).
1952      */
1953     this(size_t size = FD_SETSIZE) pure nothrow
1954     {
1955         resize(size);
1956         reset();
1957     }
1958 
1959     /// Reset the `SocketSet` so that there are 0 `Socket`s in the collection.
1960     void reset() pure nothrow @nogc
1961     {
1962         version (Windows)
1963             count = 0;
1964         else
1965         {
1966             set[] = 0;
1967             maxfd = -1;
1968         }
1969     }
1970 
1971 
1972     void add(socket_t s) @trusted pure nothrow
1973     {
1974         version (Windows)
1975         {
1976             if (count == capacity)
1977             {
1978                 set.length *= 2;
1979                 set.length = set.capacity;
1980             }
1981             ++count;
1982             fds[$-1] = s;
1983         }
1984         else
1985         {
1986             auto index = s / FD_NFDBITS;
1987             auto length = set.length;
1988             if (index >= length)
1989             {
1990                 while (index >= length)
1991                     length *= 2;
1992                 set.length = length;
1993                 // set.length = set.capacity;
1994             }
1995             set[index] |= mask(s);
1996             if (maxfd < s)
1997                 maxfd = s;
1998         }
1999     }
2000 
2001     /**
2002      * Add a `Socket` to the collection.
2003      * The socket must not already be in the collection.
2004      */
2005     void add(Socket s) pure nothrow
2006     {
2007         add(s.sock);
2008     }
2009 
2010     void remove(socket_t s) pure nothrow
2011     {
2012         version (Windows)
2013         {
2014             import std.algorithm.searching : countUntil;
2015             auto fds = fds;
2016             auto p = fds.countUntil(s);
2017             if (p >= 0)
2018                 fds[p] = fds[--count];
2019         }
2020         else
2021         {
2022             auto index = s / FD_NFDBITS;
2023             if (index >= set.length)
2024                 return;
2025             set[index] &= ~mask(s);
2026             // note: adjusting maxfd would require scanning the set, not worth it
2027         }
2028     }
2029 
2030 
2031     /**
2032      * Remove this `Socket` from the collection.
2033      * Does nothing if the socket is not in the collection already.
2034      */
2035     void remove(Socket s) pure nothrow
2036     {
2037         remove(s.sock);
2038     }
2039 
2040     int isSet(socket_t s) const pure nothrow @nogc
2041     {
2042         version (Windows)
2043         {
2044             import std.algorithm.searching : canFind;
2045             return fds.canFind(s) ? 1 : 0;
2046         }
2047         else
2048         {
2049             if (s > maxfd)
2050                 return 0;
2051             auto index = s / FD_NFDBITS;
2052             return (set[index] & mask(s)) ? 1 : 0;
2053         }
2054     }
2055 
2056 
2057     /// Return nonzero if this `Socket` is in the collection.
2058     int isSet(Socket s) const pure nothrow @nogc
2059     {
2060         return isSet(s.sock);
2061     }
2062 
2063 
2064     /**
2065      * Returns:
2066      * The current capacity of this `SocketSet`. The exact
2067      * meaning of the return value varies from platform to platform.
2068      *
2069      * Note:
2070      * Since D 2.065, this value does not indicate a
2071      * restriction, and `SocketSet` will grow its capacity as
2072      * needed automatically.
2073      */
2074     @property uint max() const pure nothrow @nogc
2075     {
2076         return cast(uint) capacity;
2077     }
2078 
2079 
2080     fd_set* toFd_set() @trusted pure nothrow @nogc
2081     {
2082         return cast(fd_set*) set.ptr;
2083     }
2084 
2085 
2086     int selectn() const pure nothrow @nogc
2087     {
2088         version (Windows)
2089         {
2090             return count;
2091         }
2092         else version (LinuxLike)
2093         {
2094             return maxfd + 1;
2095         }
2096     }
2097 }
2098 
2099 /// The level at which a socket option is defined:
2100 enum SocketOptionLevel: int
2101 {
2102     SOCKET =  SOL_SOCKET,               /// Socket level
2103     IP =      ProtocolType.IP,          /// Internet Protocol version 4 level
2104     ICMP =    ProtocolType.ICMP,        /// Internet Control Message Protocol level
2105     IGMP =    ProtocolType.IGMP,        /// Internet Group Management Protocol level
2106     GGP =     ProtocolType.GGP,         /// Gateway to Gateway Protocol level
2107     TCP =     ProtocolType.TCP,         /// Transmission Control Protocol level
2108     PUP =     ProtocolType.PUP,         /// PARC Universal Packet Protocol level
2109     UDP =     ProtocolType.UDP,         /// User Datagram Protocol level
2110     IDP =     ProtocolType.IDP,         /// Xerox NS protocol level
2111     RAW =     ProtocolType.RAW,         /// Raw IP packet level
2112     IPV6 =    ProtocolType.IPV6,        /// Internet Protocol version 6 level
2113 }
2114 
2115 /// _Linger information for use with SocketOption.LINGER.
2116 // struct Linger
2117 // {
2118 //     _clinger clinger;
2119 
2120 //     private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2121 //     private alias l_linger_t = typeof(_clinger.init.l_linger);
2122 
2123 //     /// Nonzero for _on.
2124 //     pure nothrow @nogc @property
2125 //     ref inout(l_onoff_t) on() inout return
2126 //     {
2127 //         return clinger.l_onoff;
2128 //     }
2129 
2130 //     /// Linger _time.
2131 //     pure nothrow @nogc @property
2132 //     ref inout(l_linger_t) time() inout return
2133 //     {
2134 //         return clinger.l_linger;
2135 //     }
2136 // }
2137 
2138 /// Specifies a socket option:
2139 enum SocketOption: int
2140 {
2141     DEBUG =                SO_DEBUG,            /// Record debugging information
2142     BROADCAST =            SO_BROADCAST,        /// Allow transmission of broadcast messages
2143     REUSEADDR =            SO_REUSEADDR,        /// Allow local reuse of address
2144     LINGER =               SO_LINGER,           /// Linger on close if unsent data is present
2145     OOBINLINE =            SO_OOBINLINE,        /// Receive out-of-band data in band
2146     SNDBUF =               SO_SNDBUF,           /// Send buffer size
2147     RCVBUF =               SO_RCVBUF,           /// Receive buffer size
2148     DONTROUTE =            SO_DONTROUTE,        /// Do not route
2149     SNDTIMEO =             SO_SNDTIMEO,         /// Send timeout
2150     RCVTIMEO =             SO_RCVTIMEO,         /// Receive timeout
2151     ERROR =                SO_ERROR,            /// Retrieve and clear error status
2152     KEEPALIVE =            SO_KEEPALIVE,        /// Enable keep-alive packets
2153     ACCEPTCONN =           SO_ACCEPTCONN,       /// Listen
2154     RCVLOWAT =             SO_RCVLOWAT,         /// Minimum number of input bytes to process
2155     SNDLOWAT =             SO_SNDLOWAT,         /// Minimum number of output bytes to process
2156     TYPE =                 SO_TYPE,             /// Socket type
2157 
2158     // SocketOptionLevel.TCP:
2159     TCP_NODELAY =          .TCP_NODELAY,        /// Disable the Nagle algorithm for send coalescing
2160 
2161     // SocketOptionLevel.IPV6:
2162     IPV6_UNICAST_HOPS =    .IPV6_UNICAST_HOPS,          /// IP unicast hop limit
2163     IPV6_MULTICAST_IF =    .IPV6_MULTICAST_IF,          /// IP multicast interface
2164     IPV6_MULTICAST_LOOP =  .IPV6_MULTICAST_LOOP,        /// IP multicast loopback
2165     IPV6_MULTICAST_HOPS =  .IPV6_MULTICAST_HOPS,        /// IP multicast hops
2166     IPV6_JOIN_GROUP =      .IPV6_JOIN_GROUP,            /// Add an IP group membership
2167     IPV6_LEAVE_GROUP =     .IPV6_LEAVE_GROUP,           /// Drop an IP group membership
2168     IPV6_V6ONLY =          .IPV6_V6ONLY,                /// Treat wildcard bind as AF_INET6-only
2169 }
2170 
2171 
2172 /**
2173  * Class that creates a network communication endpoint using
2174  * the Berkeley sockets interface.
2175  */
2176 class Socket
2177 {
2178 private:
2179     socket_t sock;
2180     AddressFamily _family;
2181 
2182     version (Windows)
2183         bool _blocking = true;         /// Property to get or set whether the socket is blocking or nonblocking.
2184 
2185     // The WinSock timeouts seem to be effectively skewed by a constant
2186     // offset of about half a second (value in milliseconds). This has
2187     // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2188     // and Windows Server 2008 R2 boxes. The unittest below tests this
2189     // behavior.
2190     enum WINSOCK_TIMEOUT_SKEW = 500;
2191 
2192     void setSock(socket_t handle)
2193     {
2194         assert(handle != socket_t.init);
2195         sock = handle;
2196 
2197         // Set the option to disable SIGPIPE on send() if the platform
2198         // has it (e.g. on OS X).
2199         static if (is(typeof(SO_NOSIGPIPE)))
2200         {
2201             setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2202         }
2203     }
2204 
2205 
2206     // For use with accepting().
2207     protected this() pure nothrow @nogc
2208     {
2209     }
2210 
2211 
2212 public:
2213 
2214     /**
2215      * Create a blocking socket. If a single protocol type exists to support
2216      * this socket type within the address family, the `ProtocolType` may be
2217      * omitted.
2218      */
2219     this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2220     {
2221         _family = af;
2222         auto handle = cast(socket_t) socket(af, type, protocol);
2223         if (handle == socket_t.init)
2224             throw new SocketOSException("Unable to create socket");
2225         setSock(handle);
2226     }
2227 
2228     /// ditto
2229     this(AddressFamily af, SocketType type)
2230     {
2231         /* A single protocol exists to support this socket type within the
2232          * protocol family, so the ProtocolType is assumed.
2233          */
2234         this(af, type, cast(ProtocolType) 0);         // Pseudo protocol number.
2235     }
2236 
2237 
2238     /// ditto
2239     this(AddressFamily af, SocketType type, scope const(char)[] protocolName) @trusted
2240     {
2241         protoent* proto;
2242         proto = getprotobyname(protocolName.tempCString());
2243         if (!proto)
2244             throw new SocketOSException("Unable to find the protocol");
2245         this(af, type, cast(ProtocolType) proto.p_proto);
2246     }
2247 
2248 
2249     /**
2250      * Create a blocking socket using the parameters from the specified
2251      * `AddressInfo` structure.
2252      */
2253     this(const scope AddressInfo info)
2254     {
2255         this(info.family, info.type, info.protocol);
2256     }
2257 
2258     /// Use an existing socket handle.
2259     this(socket_t sock, AddressFamily af) pure nothrow @nogc
2260     {
2261         assert(sock != socket_t.init);
2262         this.sock = sock;
2263         this._family = af;
2264     }
2265 
2266 
2267     ~this() nothrow @nogc
2268     {
2269         close();
2270     }
2271 
2272 
2273     /// Get underlying socket handle.
2274     @property socket_t handle() const pure nothrow @nogc
2275     {
2276         return sock;
2277     }
2278 
2279     /**
2280      * Releases the underlying socket handle from the Socket object. Once it
2281      * is released, you cannot use the Socket object's methods anymore. This
2282      * also means the Socket destructor will no longer close the socket - it
2283      * becomes your responsibility.
2284      *
2285      * To get the handle without releasing it, use the `handle` property.
2286      */
2287     @property socket_t release() pure nothrow @nogc
2288     {
2289         auto h = sock;
2290         this.sock = socket_t.init;
2291         return h;
2292     }
2293 
2294     /**
2295      * Get/set socket's blocking flag.
2296      *
2297      * When a socket is blocking, calls to receive(), accept(), and send()
2298      * will block and wait for data/action.
2299      * A non-blocking socket will immediately return instead of blocking.
2300      */
2301     @property bool blocking() @trusted const nothrow @nogc
2302     {
2303         version (Windows)
2304         {
2305             return _blocking;
2306         }
2307         else version (LinuxLike)
2308         {
2309             return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2310         }
2311     }
2312 
2313     /// ditto
2314     @property void blocking(bool byes) @trusted
2315     {
2316         version (Windows)
2317         {
2318             uint num = !byes;
2319             if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2320                 goto err;
2321             _blocking = byes;
2322         }
2323         else version (LinuxLike)
2324         {
2325             int x = fcntl(sock, F_GETFL, 0);
2326             if (-1 == x)
2327                 goto err;
2328             if (byes)
2329                 x &= ~O_NONBLOCK;
2330             else
2331                 x |= O_NONBLOCK;
2332             if (-1 == fcntl(sock, F_SETFL, x))
2333                 goto err;
2334         }
2335         return;         // Success.
2336 
2337  err:
2338         throw new SocketOSException("Unable to set socket blocking");
2339     }
2340 
2341 
2342     /// Get the socket's address family.
2343     @property AddressFamily addressFamily()
2344     {
2345         return _family;
2346     }
2347 
2348     /// Property that indicates if this is a valid, alive socket.
2349     @property bool isAlive() @trusted const
2350     {
2351         int type;
2352         socklen_t typesize = cast(socklen_t) type.sizeof;
2353         return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2354     }
2355 
2356     /**
2357      * Associate a local address with this socket.
2358      *
2359      * Params:
2360      *     addr = The $(LREF Address) to associate this socket with.
2361      *
2362      * Throws: $(LREF SocketOSException) when unable to bind the socket.
2363      */
2364     void bind(Address addr) @trusted
2365     {
2366         if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2367             throw new SocketOSException("Unable to bind socket");
2368     }
2369 
2370     /**
2371      * Establish a connection. If the socket is blocking, connect waits for
2372      * the connection to be made. If the socket is nonblocking, connect
2373      * returns immediately and the connection attempt is still in progress.
2374      */
2375     void connect(Address to) @trusted
2376     {
2377         if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2378         {
2379             int err;
2380             err = _lasterr();
2381 
2382             if (!blocking)
2383             {
2384                 version (Windows)
2385                 {
2386                     if (WSAEWOULDBLOCK == err)
2387                         return;
2388                 }
2389                 else version (LinuxLike)
2390                 {
2391                     if (EINPROGRESS == err)
2392                         return;
2393                 }
2394                 else
2395                 {
2396                     static assert(0);
2397                 }
2398             }
2399             throw new SocketOSException("Unable to connect socket", err);
2400         }
2401     }
2402 
2403     /**
2404      * Listen for an incoming connection. `bind` must be called before you
2405      * can `listen`. The `backlog` is a request of how many pending
2406      * incoming connections are queued until `accept`ed.
2407      */
2408     void listen(int backlog) @trusted
2409     {
2410         if (_SOCKET_ERROR == .listen(sock, backlog))
2411             throw new SocketOSException("Unable to listen on socket");
2412     }
2413 
2414     /**
2415      * Called by `accept` when a new `Socket` must be created for a new
2416      * connection. To use a derived class, override this method and return an
2417      * instance of your class. The returned `Socket`'s handle must not be
2418      * set; `Socket` has a protected constructor `this()` to use in this
2419      * situation.
2420      *
2421      * Override to use a derived class.
2422      * The returned socket's handle must not be set.
2423      */
2424     protected Socket accepting() pure nothrow
2425     {
2426         return new Socket;
2427     }
2428 
2429     /**
2430      * Accept an incoming connection. If the socket is blocking, `accept`
2431      * waits for a connection request. Throws `SocketAcceptException` if
2432      * unable to _accept. See `accepting` for use with derived classes.
2433      */
2434     Socket accept() @trusted
2435     {
2436         auto newsock = cast(socket_t).accept(sock, null, null);
2437         if (socket_t.init == newsock)
2438             return null;
2439 
2440         Socket newSocket;
2441         try
2442         {
2443             newSocket = accepting();
2444             assert(newSocket.sock == socket_t.init);
2445 
2446             newSocket.setSock(newsock);
2447             version (Windows)
2448                 newSocket._blocking = _blocking;                 //inherits blocking mode
2449             newSocket._family = _family;             //same family
2450         }
2451         catch (Throwable o)
2452         {
2453             _close(newsock);
2454             throw o;
2455         }
2456 
2457         return newSocket;
2458     }
2459 
2460     /// Disables sends and/or receives.
2461     void shutdown(SocketShutdown how) @trusted nothrow @nogc
2462     {
2463         .shutdown(sock, cast(int) how);
2464     }
2465 
2466 
2467     private static void _close(socket_t sock) @system nothrow @nogc
2468     {
2469         version (Windows)
2470         {
2471             .closesocket(sock);
2472         }
2473         else version (LinuxLike)
2474         {
2475             .close(sock);
2476         }
2477     }
2478 
2479 
2480     /**
2481      * Immediately drop any connections and release socket resources.
2482      * The `Socket` object is no longer usable after `close`.
2483      * Calling `shutdown` before `close` is recommended
2484      * for connection-oriented sockets.
2485      */
2486     void close() scope @trusted nothrow @nogc
2487     {
2488         _close(sock);
2489         sock = socket_t.init;
2490     }
2491 
2492 
2493     /**
2494      * Returns: The local machine's host name
2495      */
2496     static @property string hostName() @trusted     // getter
2497     {
2498         char[256] result;         // Host names are limited to 255 chars.
2499         if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
2500             throw new SocketOSException("Unable to obtain host name");
2501         return to!string(result.ptr);
2502     }
2503 
2504     /// Remote endpoint `Address`.
2505     @property Address remoteAddress() @trusted
2506     {
2507         Address addr = createAddress();
2508         socklen_t nameLen = addr.nameLen;
2509         if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
2510             throw new SocketOSException("Unable to obtain remote socket address");
2511         addr.setNameLen(nameLen);
2512         assert(addr.addressFamily == _family);
2513         return addr;
2514     }
2515 
2516     /// Local endpoint `Address`.
2517     @property Address localAddress() @trusted
2518     {
2519         Address addr = createAddress();
2520         socklen_t nameLen = addr.nameLen;
2521         if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
2522             throw new SocketOSException("Unable to obtain local socket address");
2523         addr.setNameLen(nameLen);
2524         assert(addr.addressFamily == _family);
2525         return addr;
2526     }
2527 
2528     /**
2529      * Send or receive error code. See `wouldHaveBlocked`,
2530      * `lastSocketError` and `Socket.getErrorText` for obtaining more
2531      * information about the error.
2532      */
2533     enum int ERROR = _SOCKET_ERROR;
2534 
2535     private static int capToInt(size_t size) nothrow @nogc
2536     {
2537         // Windows uses int instead of size_t for length arguments.
2538         // Luckily, the send/recv functions make no guarantee that
2539         // all the data is sent, so we use that to send at most
2540         // int.max bytes.
2541         return size > size_t(int.max) ? int.max : cast(int) size;
2542     }
2543 
2544     /**
2545      * Send data on the connection. If the socket is blocking and there is no
2546      * buffer space left, `send` waits.
2547      * Returns: The number of bytes actually sent, or `Socket.ERROR` on
2548      * failure.
2549      */
2550     ptrdiff_t send(scope const(void)[] buf, SocketFlags flags) @trusted
2551     {
2552         static if (is(typeof(MSG_NOSIGNAL)))
2553         {
2554             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
2555         }
2556         version (Windows)
2557             auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
2558         else
2559             auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
2560         return sent;
2561     }
2562 
2563     /// ditto
2564     ptrdiff_t send(scope const(void)[] buf)
2565     {
2566         return send(buf, SocketFlags.NONE);
2567     }
2568 
2569     /**
2570      * Send data to a specific destination Address. If the destination address is
2571      * not specified, a connection must have been made and that address is used.
2572      * If the socket is blocking and there is no buffer space left, `sendTo` waits.
2573      * Returns: The number of bytes actually sent, or `Socket.ERROR` on
2574      * failure.
2575      */
2576     ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags, Address to) @trusted
2577     {
2578         static if (is(typeof(MSG_NOSIGNAL)))
2579         {
2580             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
2581         }
2582         version (Windows)
2583             return .sendto(
2584                        sock, buf.ptr, capToInt(buf.length),
2585                        cast(int) flags, to.name, to.nameLen
2586                        );
2587         else
2588             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
2589     }
2590 
2591     /// ditto
2592     ptrdiff_t sendTo(scope const(void)[] buf, Address to)
2593     {
2594         return sendTo(buf, SocketFlags.NONE, to);
2595     }
2596 
2597 
2598     //assumes you connect()ed
2599     /// ditto
2600     ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags) @trusted
2601     {
2602         static if (is(typeof(MSG_NOSIGNAL)))
2603         {
2604             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
2605         }
2606         version (Windows)
2607             return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
2608         else
2609             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
2610     }
2611 
2612 
2613     //assumes you connect()ed
2614     /// ditto
2615     ptrdiff_t sendTo(scope const(void)[] buf)
2616     {
2617         return sendTo(buf, SocketFlags.NONE);
2618     }
2619 
2620 
2621     /**
2622      * Receive data on the connection. If the socket is blocking, `receive`
2623      * waits until there is data to be received.
2624      * Returns: The number of bytes actually received, `0` if the remote side
2625      * has closed the connection, or `Socket.ERROR` on failure.
2626      */
2627     ptrdiff_t receive(scope void[] buf, SocketFlags flags) @trusted
2628     {
2629         version (Windows)         // Does not use size_t
2630         {
2631             return buf.length
2632                    ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
2633                    : 0;
2634         }
2635         else
2636         {
2637             return buf.length
2638                    ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
2639                    : 0;
2640         }
2641     }
2642 
2643     /// ditto
2644     ptrdiff_t receive(scope void[] buf)
2645     {
2646         return receive(buf, SocketFlags.NONE);
2647     }
2648 
2649     /**
2650      * Receive data and get the remote endpoint `Address`.
2651      * If the socket is blocking, `receiveFrom` waits until there is data to
2652      * be received.
2653      * Returns: The number of bytes actually received, `0` if the remote side
2654      * has closed the connection, or `Socket.ERROR` on failure.
2655      */
2656     ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags, ref Address from) @trusted
2657     {
2658         if (!buf.length)         //return 0 and don't think the connection closed
2659             return 0;
2660         if (from is null || from.addressFamily != _family)
2661             from = createAddress();
2662         socklen_t nameLen = from.nameLen;
2663         version (Windows)
2664             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
2665 
2666         else
2667             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
2668 
2669         if (read >= 0)
2670         {
2671             from.setNameLen(nameLen);
2672             assert(from.addressFamily == _family);
2673         }
2674         return read;
2675     }
2676 
2677 
2678     /// ditto
2679     ptrdiff_t receiveFrom(scope void[] buf, ref Address from)
2680     {
2681         return receiveFrom(buf, SocketFlags.NONE, from);
2682     }
2683 
2684 
2685     //assumes you connect()ed
2686     /// ditto
2687     ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags) @trusted
2688     {
2689         if (!buf.length)         //return 0 and don't think the connection closed
2690             return 0;
2691         version (Windows)
2692         {
2693             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
2694             // if (!read) //connection closed
2695             return read;
2696         }
2697         else
2698         {
2699             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
2700             // if (!read) //connection closed
2701             return read;
2702         }
2703     }
2704 
2705 
2706     //assumes you connect()ed
2707     /// ditto
2708     ptrdiff_t receiveFrom(scope void[] buf)
2709     {
2710         return receiveFrom(buf, SocketFlags.NONE);
2711     }
2712 
2713 
2714     /**
2715      * Get a socket option.
2716      * Returns: The number of bytes written to `result`.
2717      * The length, in bytes, of the actual result - very different from getsockopt()
2718      */
2719     int getOption(SocketOptionLevel level, SocketOption option, scope void[] result) @trusted
2720     {
2721         socklen_t len = cast(socklen_t) result.length;
2722         if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
2723             throw new SocketOSException("Unable to get socket option");
2724         return len;
2725     }
2726 
2727 
2728     /// Common case of getting integer and boolean options.
2729     int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
2730     {
2731         return getOption(level, option, (&result)[0 .. 1]);
2732     }
2733 
2734 
2735     /// Get the linger option.
2736     // int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
2737     // {
2738     //     //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
2739     //     return getOption(level, option, (&result.clinger)[0 .. 1]);
2740     // }
2741 
2742     /// Set a socket option.
2743     void setOption(SocketOptionLevel level, SocketOption option, scope void[] value) @trusted
2744     {
2745         if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
2746                                         cast(int) option, value.ptr, cast(uint) value.length))
2747             throw new SocketOSException("Unable to set socket option");
2748     }
2749 
2750 
2751     /// Common case for setting integer and boolean options.
2752     void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
2753     {
2754         setOption(level, option, (&value)[0 .. 1]);
2755     }
2756 
2757 
2758     /// Set the linger option.
2759     // void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
2760     // {
2761     //     //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
2762     //     setOption(level, option, (&value.clinger)[0 .. 1]);
2763     // }
2764     /**
2765      * Get a text description of this socket's error status, and clear the
2766      * socket's error status.
2767      */
2768     string getErrorText()
2769     {
2770         int32_t error;
2771         getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
2772         return formatSocketError(error);
2773     }
2774 
2775     /**
2776      * Enables TCP keep-alive with the specified parameters.
2777      *
2778      * Params:
2779      *   time     = Number of seconds with no activity until the first
2780      *              keep-alive packet is sent.
2781      *   interval = Number of seconds between when successive keep-alive
2782      *              packets are sent if no acknowledgement is received.
2783      *
2784      * Throws: `SocketOSException` if setting the options fails, or
2785      * `SocketFeatureException` if setting keep-alive parameters is
2786      * unsupported on the current platform.
2787      */
2788     void setKeepAlive(int time, int interval) @trusted
2789     {
2790         version (Windows)
2791         {
2792             tcp_keepalive options;
2793             options.onoff = 1;
2794             options.keepalivetime = time * 1000;
2795             options.keepaliveinterval = interval * 1000;
2796             uint cbBytesReturned;
2797             enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
2798                              &options, options.sizeof,
2799                              null, 0,
2800                              &cbBytesReturned, null, null) == 0,
2801                     new SocketOSException("Error setting keep-alive"));
2802         }
2803         else
2804         static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
2805         {
2806             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
2807             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
2808             setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
2809         }
2810         else
2811             throw new SocketFeatureException("Setting keep-alive options " ~
2812                 "is not supported on this platform");
2813     }
2814 
2815     // /// ditto
2816     // //maximum timeout
2817     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
2818     {
2819         return select(checkRead, checkWrite, checkError, null);
2820     }
2821 
2822     /// Ditto
2823     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
2824     in
2825     {
2826         //make sure none of the SocketSet's are the same object
2827         if (checkRead)
2828         {
2829             assert(checkRead !is checkWrite);
2830             assert(checkRead !is checkError);
2831         }
2832         if (checkWrite)
2833         {
2834             assert(checkWrite !is checkError);
2835         }
2836     }
2837     do
2838     {
2839         fd_set* fr, fw, fe;
2840         int n = 0;
2841 
2842         version (Windows)
2843         {
2844             // Windows has a problem with empty fd_set`s that aren't null.
2845             fr = checkRead  && checkRead.count  ? checkRead.toFd_set()  : null;
2846             fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
2847             fe = checkError && checkError.count ? checkError.toFd_set() : null;
2848         }
2849         else
2850         {
2851             if (checkRead)
2852             {
2853                 fr = checkRead.toFd_set();
2854                 n = checkRead.selectn();
2855             }
2856             else
2857             {
2858                 fr = null;
2859             }
2860 
2861             if (checkWrite)
2862             {
2863                 fw = checkWrite.toFd_set();
2864                 int _n;
2865                 _n = checkWrite.selectn();
2866                 if (_n > n)
2867                     n = _n;
2868             }
2869             else
2870             {
2871                 fw = null;
2872             }
2873 
2874             if (checkError)
2875             {
2876                 fe = checkError.toFd_set();
2877                 int _n;
2878                 _n = checkError.selectn();
2879                 if (_n > n)
2880                     n = _n;
2881             }
2882             else
2883             {
2884                 fe = null;
2885             }
2886 
2887             // Make sure the sets' capacity matches, to avoid select reading
2888             // out of bounds just because one set was bigger than another
2889             if (checkRead ) checkRead .setMinCapacity(n);
2890             if (checkWrite) checkWrite.setMinCapacity(n);
2891             if (checkError) checkError.setMinCapacity(n);
2892         }
2893 
2894         int result = .select(n, fr, fw, fe, &timeout.ctimeval);
2895 
2896         version (Windows)
2897         {
2898             if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
2899                 return -1;
2900         }
2901         else version (LinuxLike)
2902         {
2903             if (_SOCKET_ERROR == result && errno == EINTR)
2904                 return -1;
2905         }
2906         else
2907         {
2908             static assert(0);
2909         }
2910 
2911         if (_SOCKET_ERROR == result)
2912             throw new SocketOSException("Socket select error");
2913 
2914         return result;
2915     }
2916 
2917 
2918     /**
2919      * Can be overridden to support other addresses.
2920      * Returns: A new `Address` object for the current address family.
2921      */
2922     protected Address createAddress() pure nothrow
2923     {
2924         Address result;
2925         switch (_family)
2926         {
2927         static if (is(sockaddr_un))
2928         {
2929             case AddressFamily.UNIX:
2930                 result = new UnixAddress;
2931                 break;
2932         }
2933 
2934         case AddressFamily.INET:
2935             result = new InternetAddress;
2936             break;
2937 
2938         case AddressFamily.INET6:
2939             result = new Internet6Address;
2940             break;
2941 
2942         default:
2943             result = new UnknownAddress;
2944         }
2945         return result;
2946     }
2947 
2948 }
2949 
2950 
2951 /// Shortcut class for a TCP Socket.
2952 class TcpSocket: Socket
2953 {
2954     /// Constructs a blocking TCP Socket.
2955     this(AddressFamily family)
2956     {
2957         super(family, SocketType.STREAM, ProtocolType.TCP);
2958     }
2959 
2960     /// Constructs a blocking IPv4 TCP Socket.
2961     this()
2962     {
2963         this(AddressFamily.INET);
2964     }
2965 
2966 
2967     //shortcut
2968     /// Constructs a blocking TCP Socket and connects to the given `Address`.
2969     this(Address connectTo)
2970     {
2971         this(connectTo.addressFamily);
2972         connect(connectTo);
2973     }
2974 }
2975 
2976 
2977 /// Shortcut class for a UDP Socket.
2978 class UdpSocket: Socket
2979 {
2980     /// Constructs a blocking UDP Socket.
2981     this(AddressFamily family)
2982     {
2983         super(family, SocketType.DGRAM, ProtocolType.UDP);
2984     }
2985 
2986 
2987     /// Constructs a blocking IPv4 UDP Socket.
2988     this()
2989     {
2990         this(AddressFamily.INET);
2991     }
2992 }
2993 
2994 
2995 
2996 /**
2997  * Creates a pair of connected sockets.
2998  *
2999  * The two sockets are indistinguishable.
3000  *
3001  * Throws: `SocketException` if creation of the sockets fails.
3002  */
3003 Socket[2] socketPair() @trusted
3004 {
3005     version (LinuxLike)
3006     {
3007         int[2] socks;
3008         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3009             throw new SocketOSException("Unable to create socket pair");
3010 
3011         Socket toSocket(size_t id)
3012         {
3013             auto s = new Socket;
3014             s.setSock(cast(socket_t) socks[id]);
3015             s._family = AddressFamily.UNIX;
3016             return s;
3017         }
3018 
3019         return [toSocket(0), toSocket(1)];
3020     }
3021     else version (Windows)
3022     {
3023         // We do not have socketpair() on Windows, just manually create a
3024         // pair of sockets connected over some localhost port.
3025         Socket[2] result;
3026 
3027         auto listener = new TcpSocket();
3028         listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3029         listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3030         auto addr = listener.localAddress;
3031         listener.listen(1);
3032 
3033         result[0] = new TcpSocket(addr);
3034         result[1] = listener.accept();
3035 
3036         listener.close();
3037         return result;
3038     }
3039     else
3040         static assert(false);
3041 }
3042 
3043 ///